package cn.lyf.conf;

import cn.lyf.App;
import cn.lyf.aop.LogAspect;
import cn.lyf.bean.Car;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.springframework.context.annotation.*;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;
import java.beans.PropertyVetoException;

//这是一个配置文件
//@Import 用class直接导入组件,或ImportSelector返回类名,ImportBeanDefinitionRegistrar
@Configuration
//开启aop代理
/*
注入了一个AspectJAutoProxyRegistrar.class
AspectJAutoProxyRegistrar是 ImportBeanDefinitionRegistrar
注册了个AnnotationAwareAspectJAutoProxyCreator
该类是后置处理器实现了InstantiationAwareBeanPostProcessor，并且注入了beanFactory
spring 调用resolveBeforeInstantiation 返回一个代理对象
*/
@EnableAspectJAutoProxy
// 载入外部配置
// @PropertySource(value ={"classpath:/conf.properties"，encoding="utf-8"})
@ComponentScan(value = "cn.lyf.bean", includeFilters = {
        @Filter(type = FilterType.CUSTOM, classes = {MyTypeFilter.class}),
        @Filter(type = FilterType.ANNOTATION, classes = {Service.class})}, useDefaultFilters = false)
@ComponentScan("cn.lyf.listener")
// @ComponentScans @Repeatable
// 开启事务管理
/*
导入了 TransactionManagementConfigurationSelector 实现了ImportSelector
    1） 导入AutoProxyRegister, ProxyTransactionManagementConfiguration
        继承了ImportBeanDefinitionRegistrar
    ===========
    1） AutoProxyRegister  调用  registerAutoProxyCreatorIfNecessary 注册 InfrastructureAdvisorAutoProxyCreator
                AnnotationAwareAspectJAutoProxyCreator
    2） ProxyTransactionManagementConfiguration 给容器中注册事务增强器
         1） 保存事务要用的注解信息
         2） 事务拦截器
            1) TransactionInterceptor 保存事务信息，事务管理器；本质是一个MethodInterceptor
    ==========
    BeanFactoryProcessor
        BeanDefinitionRegistryPostProcessor
    ==========
   ApplicationListener

*/
@EnableTransactionManagement
public class MainConfig {
    // @Bean @Scope @Lazy
    // @Conditional

    @Bean(initMethod = "init", destroyMethod = "destroy")
        // 多实例的bean要自行销毁
    Car car() {
        return new Car();
    }

    // @PostConstruct 在bean初始化并赋好值后 调用
    // @PreDestroy 在bean销毁前 调用
    // 依赖注入
    // @Value 中可以填基本类型，SpEl表达式，或${}取出环境中的值
    // @Autowired构造器，参数，方法，属性都可以标注
    // @Qualifier("") @Autowired(require=false)；@Primary 设置默认
    // @Resource("") @Inject
    // 构造器注入 https://blog.csdn.net/qq271859852/article/details/105181422/
    //StringValeResolver 用来解析spring 表达式
    //xxxAware 用 xxxProcessor 处理
    //@Profile() 设置环境 ，通过虚拟机参数 -Dspring.profiles.active=xxx

    @Bean
    LogAspect logAspect() {
        return new LogAspect();
    }

    @Bean
    App app() {
        return new App();
    }

//    @Transactional

    @Bean
    //注册事务管理器
    public PlatformTransactionManager transactionManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean
    public JdbcTemplate jdbcTemplate(DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }

    @Bean
    public DataSource dataSource() throws PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setUser("root");
        dataSource.setPassword("123456");
        dataSource.setDriverClass("com.mysql.jdbc.Driver");
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
        return dataSource;
    }

}
// InstantiationAwareBeanPostProcessor 实例化后置处理器
